home *** CD-ROM | disk | FTP | other *** search
- /************************************************************************/
- /* */
- /* Write image as ilbm */
- /* */
- /* */
- /* */
- /* */
- /************************************************************************/
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
-
- #include <exec/types.h>
- #include <datatypes/pictureclass.h>
-
- #include <scanner.h>
- #include <MakeILBM.h>
- #include <packer.h>
-
- #define ID_XBMI MAKE_ID('X','B','M','I')
- #define ILBM_BUFLEN 1500000
-
- struct ImageBuf
- {
- UBYTE* buf;
- ULONG actualLen;
- FILE* fh;
- };
-
- struct ILBMFile
- {
- char* fileName;
- int formLenOffset;
- int bodyLenOffset;
- UBYTE flags;
-
- UBYTE depth;
- UWORD width;
- UWORD height;
- UWORD xdpi;
- UWORD ydpi;
-
- LineFormat format;
-
- ULONG scanLineWidth;
- ULONG bufLen;
- struct ImageBuf buf[3];
- };
-
- #define ILBMFLAGS_COMPRESS (0x01 << 0)
- #define ILBMFLAGS_TEMPFILE (0x01 << 1)
-
- struct xbmi
- {
- WORD xbmi_type; /* ILBM_PAL, ILBM_RGB, ... (se below) */
- WORD xbmi_xdpi;
- WORD xbmi_ydpi;
- };
-
-
- #define ILBM_PAL 0 /* BODY data = indexes into the palette (CMAP)
- * numcolors = 1<<depth;
- */
-
- #define ILBM_GREY 1 /* BODY = grayscale values
- * Bits per sample = number of bitplanes.
- * Samples per pixel = 1.
- * black = 0, white = (1<<depth)-1;
- */
-
- #define ILBM_RGB 2 /* BODY data = red, green, and blue values.
- * Bits per sample = depth/3.
- * Samples per pixel = 3.
- */
-
- #define ILBM_RGBA 3 /* BODY data = red, green, blue, and alpha
- * channel values.
- * Bits per sample = depth/4.
- * Samples per pixel = 4.
- */
-
- #define ILBM_CMYK 4 /* BODY data = cyan, magenta, yellow, and black
- * values.
- * Bits per sample = depth/4.
- * Samples per pixel = 4.
- */
-
- #define ILBM_CMYKA 5 /* BODY data = cyan, magenta, yellow, black,
- * and alpha channel values.
- * Bits per sample = depth/5.
- * Samples per pixel = 5.
- */
-
- #define ILBM_BW 6 /* BODY data = black and white bits.
- * Bits per sample = 1.
- * Samples per pixel = 1.
- * white = 0, black = 1.
- */
-
- static char* tempfile[3] = {"ram:temp.red","ram:temp.green","ram:temp.blue"};
-
- static void makePlane(UBYTE* source,UBYTE* dest,int bit,int pixelPerLine,int bytesPerPixel)
- {
- int bitNum,byteNum,offset;
- UBYTE b,sourceMask;
-
- offset = bit/8;
- bit %= 8;
-
- sourceMask = 0x01 << bit;
-
- source += offset;
- for( byteNum = 0 ; byteNum < pixelPerLine ; byteNum++ )
- {
- UBYTE destMask;
-
- destMask = 0x80;
- b = 0;
- for( bitNum = 0 ; bitNum < 8 ; bitNum++ )
- {
- if( (*source) & sourceMask )
- b |= destMask;
-
- destMask >>= 1;
- source += bytesPerPixel;
- }
- *(dest++) = b;
- }
- }
-
- static void makeILBM(struct ILBMFile* ilbmfh)
- {
- struct BitMapHeader BMHD;
- struct xbmi XBMI;
- FILE* fh;
- int c;
-
- if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
- {
- for( c = 0 ; c < 3 ; c++ )
- {
- if( ilbmfh->buf[c].fh && (ilbmfh->buf[c].fh = fopen(tempfile[c],"r")) )
- setvbuf(ilbmfh->buf[c].fh,ilbmfh->buf[c].buf,_IOFBF,ilbmfh->bufLen);
- }
- }
-
- BMHD.bmh_Width = ilbmfh->width;
- BMHD.bmh_Height = ilbmfh->height;
- BMHD.bmh_Left = 0;
- BMHD.bmh_Top = 0;
- BMHD.bmh_Depth = ilbmfh->depth;
- BMHD.bmh_Masking = 0;
- BMHD.bmh_Pad = 0;
- BMHD.bmh_Transparent = 0;
- BMHD.bmh_XAspect = 1;
- BMHD.bmh_YAspect = 1;
- BMHD.bmh_PageWidth = ilbmfh->width;
- BMHD.bmh_PageHeight = ilbmfh->height;
-
- switch( ilbmfh->depth )
- {
- case 1:
- XBMI.xbmi_type = ILBM_BW;
- break;
- case 8:
- XBMI.xbmi_type = ILBM_GREY;
- break;
- case 24:
- XBMI.xbmi_type = ILBM_RGB;
- break;
- }
- XBMI.xbmi_xdpi = ilbmfh->xdpi;
- XBMI.xbmi_ydpi = ilbmfh->ydpi;
-
- if( fh = fopen(ilbmfh->fileName,"w") )
- {
- int scanLine,color,bitNum;
- ULONG lineLen,bodyLen,formLen;
- ULONG temp,psize;
- UBYTE *line;
- UBYTE *pline = NULL;
- UBYTE *scanbuf = NULL;
-
- lineLen = ((ilbmfh->width+7)/8+1) & 0xFFFFFFFE; // Number of bits in each plane row
- // Rounded up to an even number of words
- line = malloc(ilbmfh->format==FORMAT_RGB?3*lineLen:lineLen);
- if( (ilbmfh->flags & ILBMFLAGS_COMPRESS) && (pline = malloc(ilbmfh->format==FORMAT_RGB?6*lineLen:lineLen*2)) )
- BMHD.bmh_Compression = 1;
- else
- BMHD.bmh_Compression = 0;
-
- temp = ID_FORM;
- fwrite(&temp,4,1,fh);
- ilbmfh->formLenOffset = ftell(fh);
- temp = 0;
- fwrite(&temp,4,1,fh);
-
- temp = ID_ILBM;
- fwrite(&temp,4,1,fh);
-
- temp = ID_BMHD;
- fwrite(&temp,4,1,fh);
- temp = sizeof(struct BitMapHeader);
- fwrite(&temp,4,1,fh);
- fwrite(&BMHD,sizeof(struct BitMapHeader),1,fh);
-
- temp = ID_XBMI;
- fwrite(&temp,4,1,fh);
- temp = sizeof(struct xbmi);
-
- fwrite(&temp,4,1,fh);
- fwrite(&XBMI,sizeof(struct xbmi),1,fh);
-
- if( ilbmfh->depth == 1 )
- {
- UBYTE b;
-
- temp = ID_CMAP;
- fwrite(&temp,4,1,fh);
- temp = 3*2;;
- fwrite(&temp,4,1,fh);
-
- b = 0xFF;
- fwrite(&b,1,1,fh);
- fwrite(&b,1,1,fh);
- fwrite(&b,1,1,fh);
-
- b = 0;
- fwrite(&b,1,1,fh);
- fwrite(&b,1,1,fh);
- fwrite(&b,1,1,fh);
- }
- else if( ilbmfh->depth == 8 )
- {
- UBYTE b;
- int i;
-
- temp = ID_CMAP;
- fwrite(&temp,4,1,fh);
- temp = 3*256;;
- fwrite(&temp,4,1,fh);
- for( i = 0 ; i < 256 ; i++ )
- {
- b = (UBYTE)i;
- fwrite(&b,1,1,fh);
- fwrite(&b,1,1,fh);
- fwrite(&b,1,1,fh);
- }
- }
-
- temp = ID_BODY;
- fwrite(&temp,4,1,fh);
- ilbmfh->bodyLenOffset = ftell(fh);
- temp = 0;
- fwrite(&temp,4,1,fh);
-
- if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
- scanbuf = malloc(ilbmfh->scanLineWidth);
-
- switch( ilbmfh->format )
- {
- case FORMAT_BW:
- for( scanLine = 0 ; scanLine < ilbmfh->height ; scanLine++ )
- {
- if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
- fread(scanbuf,ilbmfh->scanLineWidth,1,ilbmfh->buf[0].fh);
- else
- scanbuf = ilbmfh->buf[0].buf + scanLine*ilbmfh->scanLineWidth;
-
- if( pline == NULL )
- fwrite(scanbuf,lineLen,1,fh);
- else
- {
- psize = PackRow(scanbuf,pline,lineLen);
- fwrite(pline,psize,1,fh);
- }
- }
- break;
- case FORMAT_GRAY:
- case FORMAT_RED:
- case FORMAT_GREEN:
- case FORMAT_BLUE:
- for( scanLine = 0 ; scanLine < ilbmfh->height ; scanLine++ )
- {
- if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
- fread(scanbuf,ilbmfh->scanLineWidth,1,ilbmfh->buf[0].fh);
- else
- scanbuf = ilbmfh->buf[0].buf + scanLine*ilbmfh->scanLineWidth;
- for( bitNum = 0 ; bitNum < 8 ; bitNum++ )
- {
- makePlane(scanbuf,line,bitNum,lineLen,1);
- if( pline == NULL )
- fwrite(line,lineLen,1,fh);
- else
- {
- psize = PackRow(line,pline,lineLen);
- fwrite(pline,psize,1,fh);
- }
- }
- }
- break;
- case FORMAT_RGB:
- for( scanLine = 0 ; scanLine < ilbmfh->height ; scanLine++ )
- {
- if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
- fread(scanbuf,ilbmfh->scanLineWidth,1,ilbmfh->buf[0].fh);
- else
- scanbuf = ilbmfh->buf[0].buf + scanLine*ilbmfh->scanLineWidth;
- for( bitNum = 0 ; bitNum < 24 ; bitNum++ )
- {
- makePlane(scanbuf,line,bitNum,lineLen,3);
- if( pline == NULL )
- fwrite(line,lineLen,1,fh);
- else
- {
- psize = PackRow(line,pline,lineLen);
- fwrite(pline,psize,1,fh);
- }
- }
- }
- break;
- case FORMAT_RGB_RANDOM:
- for( scanLine = 0 ; scanLine < ilbmfh->height ; scanLine++ )
- {
- for( color = 0 ; color < 3 ; color++ )
- {
- if( ilbmfh->buf[color].buf )
- {
- if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
- fread(scanbuf,ilbmfh->scanLineWidth,1,ilbmfh->buf[color].fh);
- else
- scanbuf = ilbmfh->buf[color].buf + scanLine*ilbmfh->scanLineWidth;
- for( bitNum = 0 ; bitNum < 8 ; bitNum++ )
- {
- makePlane(scanbuf,line,bitNum,lineLen,1);
- if( pline == NULL )
- fwrite(line,lineLen,1,fh);
- else
- {
- psize = PackRow(line,pline,lineLen);
- fwrite(pline,psize,1,fh);
- }
- }
- }
- }
- }
- break;
- }
- free(line);
- if( pline )
- free(pline);
- if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
- free(scanbuf);
-
- for( color = 0 ; color < 3 ; color++ )
- {
- if( ilbmfh->buf[color].fh )
- fclose(ilbmfh->buf[color].fh);
- if( ilbmfh->buf[color].buf )
- free(ilbmfh->buf[color].buf);
- }
-
- // Write FORM and BODY length
- formLen = ftell(fh) - ilbmfh->formLenOffset - 4;
- bodyLen = ftell(fh) - ilbmfh->bodyLenOffset - 4;
-
- fseek(fh,ilbmfh->formLenOffset,SEEK_SET);
- fwrite(&formLen,4,1,fh);
-
- fseek(fh,ilbmfh->bodyLenOffset,SEEK_SET);
- fwrite(&bodyLen,4,1,fh);
-
- fclose(fh);
- }
- }
-
-
- struct ILBMFile *openILBM(char* name,short compr,struct ScanInformation* info)
- {
- struct ILBMFile* fh;
-
- if( fh = calloc(1,sizeof(struct ILBMFile)) )
- {
- fh->fileName = name;
- if( compr )
- fh->flags = ILBMFLAGS_COMPRESS;
- else
- fh->flags = 0;
- fh->depth = info->sv_imageDepth;
- fh->width = info->sv_imageWidth;
- fh->height = info->sv_imageHeight;
- fh->xdpi = (UWORD)(info->sv_xResolution+0.5);
- fh->ydpi = (UWORD)(info->sv_yResolution+0.5);
- fh->format = info->sv_lineFormat;
- fh->scanLineWidth = info->sv_bytesPerLine;
- fh->bufLen = fh->scanLineWidth*fh->height;
-
- switch( fh->format )
- {
- case FORMAT_BW:
- case FORMAT_GRAY:
- case FORMAT_RED:
- case FORMAT_GREEN:
- case FORMAT_BLUE:
- case FORMAT_RGB:
- if( fh->bufLen > ILBM_BUFLEN )
- fh->bufLen = ILBM_BUFLEN;
- fh->buf[0].buf = malloc(fh->bufLen);
- break;
- case FORMAT_RGB_RANDOM:
- {
- int c;
-
- if( 3*fh->bufLen > ILBM_BUFLEN )
- fh->bufLen = ILBM_BUFLEN/3;
-
- for( c = 0 ; c < 3 ; c++ )
- fh->buf[c].buf = malloc(fh->bufLen);
- }
- break;
- default:
- free(fh);
- return NULL;
- }
- }
-
- return fh;
- }
-
- void closeILBM(struct ILBMFile* ilbmfh,short error)
- {
- int c;
-
- if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
- {
- for( c = 0 ; c < 3 ; c++ )
- {
- if( ilbmfh->buf[c].fh )
- {
- fwrite(ilbmfh->buf[c].buf,ilbmfh->buf[c].actualLen,1,ilbmfh->buf[c].fh);
- fclose(ilbmfh->buf[c].fh);
- // ilbmfh->buf[c].fh = NULL;
- }
- }
- }
-
- if( !error )
- makeILBM(ilbmfh);
-
- if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
- {
- for( c = 0 ; c < 3 ; c++ )
- remove(tempfile[c]);
- }
-
- free(ilbmfh);
- }
-
- void writeILBM(struct ILBMFile* fh,struct ScanLine* line)
- {
- int cPlane;
-
- if( fh->format == FORMAT_RGB_RANDOM )
- {
- switch( line->sl_color )
- {
- case FORMAT_RED:
- cPlane = 0;
- break;
- case FORMAT_GREEN:
- cPlane = 1;
- break;
- case FORMAT_BLUE:
- cPlane = 2;
- break;
- default:
- return;
- }
- }
- else
- cPlane = 0;
-
- if( fh->buf[cPlane].actualLen + fh->scanLineWidth > fh->bufLen )
- {
- if( fh->buf[cPlane].fh == NULL )
- {
- if( fh->buf[cPlane].fh = fopen(tempfile[cPlane],"w") )
- fh->flags |= ILBMFLAGS_TEMPFILE;
- else
- return;
- }
-
- fwrite(fh->buf[cPlane].buf,fh->buf[cPlane].actualLen,1,fh->buf[cPlane].fh);
- fh->buf[cPlane].actualLen = 0;
- }
-
- memcpy(fh->buf[cPlane].buf+fh->buf[cPlane].actualLen,line->sl_data,fh->scanLineWidth);
- fh->buf[cPlane].actualLen += fh->scanLineWidth;
- }
-